package com.zb.store.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.zb.constant.CodeConstant;
import com.zb.constant.StoreConstant;
import com.zb.entity.*;
import com.zb.extend.StoreInboundMaterialExtend;
import com.zb.result.PageUtil;
import com.zb.service.*;
import com.zb.service.impl.StoreBoundServiceLog;
import com.zb.store.service.ConStoreInboundService;
import com.zb.utils.ZbOrderNoUtil;
import com.zb.view.*;
import com.zb.vo.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author WEN
 * @Date 2024/1/12 0012
 **/
@Service
public class ConStoreInboundServiceImpl implements ConStoreInboundService {
    @Resource
    private ZjStoreInboundService storeInboundService;
    @Resource
    private ZjStoreTypeService storeTypeService;
    @Resource
    private ViewGoodsService viewGoodsService;
    @Resource
    private ZjCodeService codeService;
    @Resource
    private ZjStorePositionService storePositionService;
    @Resource
    private ZjStoreGoodsStockCodeService storeGoodsStockCodeService;
    @Resource
    private ZjStoreInboundMaterialService storeInboundMaterialService;
    @Resource
    private ZjStoreInboundMaterialCodeService storeInboundMaterialCodeService;
    @Resource
    private ZjStoreSetService storeSetService;
    @Resource
    private ZjStoreGoodsStockService storeGoodsStockService;
    @Resource
    private ZjStoreLogisticsService storeLogisticsService;
    @Resource
    private ZjStoreInboundOrderSpareService storeInboundOrderSpareService;
    @Resource
    private ViewStoreStoreGoodsStockService viewStoreStoreGoodsStockService;


    // 保存或保存并审核入库单
    @Override
    @Transactional
    public void save(AccounLoginInfo loginInfo, String submitType, ZjStoreInboundOrderSpare inboundOrderSpare, StoreInboundVo inboundVo) {
        String inboundNo = "";
        if (null != inboundVo.getId()) {
            ZjStoreInbound inbound = storeInboundService.getById(inboundVo.getId());
            Assert.notNull(inbound, "入库单参数[ " + inboundVo.getId() + " ]的单据数据不存在");
            Assert.isTrue(Objects.equals(StoreConstant.STORE_IN_STATUS_1, inbound.getStatus()),
                    Objects.equals(StoreConstant.STORE_IN_STATUS_2, inbound.getStatus())? "入库单已审核，禁止重复审核" :
                    Objects.equals(StoreConstant.STORE_IN_STATUS_3, inbound.getStatus())? "入库单已被审核驳回，禁止重复操作" :
                            Objects.equals(StoreConstant.STORE_IN_STATUS_4, inbound.getStatus())? "入库单已完成入库，禁止重复操作" : "入库单已作废，禁止重复操作"
            );
            inboundNo = inbound.getCode();
        }
        ZjStoreType storeType = storeTypeService.getById(inboundVo.getTypeId());
        Assert.notNull(storeType, "入库类型参数[ "+inboundVo.getTypeId()+" ]不存在系统中");

        List<StoreBoundMaterialVo> boundMaterialVos = inboundVo.getInboundMaterialVos();
        List<Long> goodsIds = boundMaterialVos.stream().map(StoreBoundMaterialVo::getGoodsId).distinct().toList();;
        List<Long> goodsSpecIds = boundMaterialVos.stream().map(StoreBoundMaterialVo::getGoodsSpecId).distinct().toList();
        List<ViewGoods> viewGoodsList = viewGoodsService.getByGoodsIdsAndGoodsSpecIds(goodsIds, goodsSpecIds);
        // 根据商品ID+规格ID存储商品对象
        Map<String, ViewGoods> viewGoodsMap = new HashMap<>();
        ViewGoods viewGoods = null;
        List<Long> storeIds = new ArrayList<>();
        // 校验入库商品物料
        for (StoreBoundMaterialVo vo : boundMaterialVos) {
            viewGoods = viewGoodsList.stream().filter(f -> Objects.equals(f.getGoodsType(), vo.getType()) && Objects.equals(f.getId(), vo.getGoodsId())
                    && Objects.equals(f.getSpecId(), vo.getGoodsSpecId())).findFirst().orElse(null);
            // 判断入库物料是否存在系统
            Assert.notNull(viewGoods, "入库商品型号规格参数[ " + vo.getGoodsId() + " " + vo.getGoodsSpecId() + " ]的物料数据在系统中不存在");
            // 校验仓库是否为空
            Assert.isTrue(null != vo.getStoreId() && vo.getStoreId() > 0, "入库商品型号规格[ "+ viewGoods.getModel() + " " + viewGoods.getSpecName() +" ]的入库仓库不能为空");
            storeIds.add(vo.getStoreId());
            vo.setStorePositionId(null == vo.getStorePositionId()? 0L : vo.getStorePositionId());
            viewGoodsMap.putIfAbsent(vo.getType() + "_" + vo.getGoodsId() + "_" + vo.getGoodsSpecId(), viewGoods);
        }
        // 根据仓库ID获取仓库及仓库商品库存
        List<ViewStoreStoreGoodsStock> storeStoreGoodsStockList = viewStoreStoreGoodsStockService.getByStoreIds(storeIds);
        // 存储入库物料编码
        List<String> codes = new ArrayList<>();
         // 校验仓库
        checkStore(codes, storeStoreGoodsStockList, boundMaterialVos, viewGoodsMap);

        List<ZjCode> codeList = new ArrayList<>();
        List<ZjStoreGoodsStockCode> storeGoodsStockCodes = new ArrayList<>();
        ZjStoreGoodsStockCode storeGoodsStockCode = null;
        // 校验一物一码，非工单配件入库时执行
        if (null == inboundOrderSpare) {
            checkCode(loginInfo, codeList, codes, storeType, inboundVo.getTypeId(), inboundVo.getId(), storeGoodsStockCodes, boundMaterialVos, viewGoodsList);
        }
        // 更新时，查询判断提交的一物一码与存在的一物一码做对比，
        // 1.提交与存在的一物一码相同，则不理会
        // 2.提交与存在的一物一码不相同，则删除存在一物一码，保存提交的一物一码
        List<Long> delCodeIds = new ArrayList<>();
        Map<String, Boolean> existCodeMap = new HashMap<>();
        if (null != inboundVo.getId()) {
            // 更新时间，查询判断提交的与系统存在的入库物料做对比
            List<ZjStoreInboundMaterial> inboundMaterialList = storeInboundMaterialService.getbyStoreInboundId(inboundVo.getId());
            List<ZjStoreInboundMaterialCode> materialCodes = storeInboundMaterialCodeService.getbyStoreInboundId(inboundVo.getId());
            Map<String, Long> codeMap = materialCodes.stream().collect(Collectors.toMap(ZjStoreInboundMaterialCode::getCode, ZjStoreInboundMaterialCode::getCodeId));
            ZjStoreInboundMaterial inboundMaterial = null;
            for (StoreBoundMaterialVo vo : boundMaterialVos) {
                // 判断删除的与更新的物料是否存在相同，相同则把删除的物料ID移除
                if (inboundVo.getDelInboundMaterialIds().stream().anyMatch(f -> Objects.equals(f, vo.getId()))) {
                    inboundVo.getDelInboundMaterialIds().remove(vo.getId());
                }
                inboundMaterial = inboundMaterialList.stream().filter(f -> Objects.equals(f.getType(), vo.getType()) && Objects.equals(f.getStoreId(), vo.getStoreId()) && Objects.equals(f.getStorePositionId(), vo.getStorePositionId())
                        && Objects.equals(f.getGoodsId(), vo.getGoodsId()) && Objects.equals(f.getGoodsSpecId(), vo.getGoodsSpecId()) && Objects.equals(f.getPrice().floatValue(), vo.getPrice().floatValue())).findFirst().orElse(null);
                if (null != inboundMaterial) {
                    vo.setId(inboundMaterial.getId());
                    inboundMaterialList.remove(inboundMaterial);
                }
                for (StoreGoodsStockCodeVo codeVo : vo.getStockCodeVos()) {
                    if (null != codeMap.get(codeVo.getCode())) {
                        existCodeMap.put(codeVo.getCode(), true);
                        codeMap.remove(codeVo.getCode()); // 存在的则移除，剩下的表示删除的
                    }
                }
            }
            // 获取删除一物一码的ID
            if (CollectionUtil.isNotEmpty(inboundVo.getDelInboundMaterialIds())) {
                for (Long materialId : inboundVo.getDelInboundMaterialIds()) {
                    if (materialCodes.stream().anyMatch(f -> Objects.equals(f.getStoreInboundMaterialId(), materialId))) {
                        delCodeIds.addAll(materialCodes.stream().filter(f -> Objects.equals(f.getStoreInboundMaterialId(), materialId)).map(ZjStoreInboundMaterialCode::getCodeId).toList());
                    }
                }
            }
            // 获取删除的一物一码
            for (Map.Entry<String, Long> entry : codeMap.entrySet()) {
                if (!delCodeIds.contains(entry.getValue())) {
                    delCodeIds.add(entry.getValue());
                }
            }
        }
        ZjStoreInbound inbound = new ZjStoreInbound();
        BeanUtil.copyProperties(inboundVo, inbound);
        inbound.setStatus(StoreConstant.STORE_IN_STATUS_1);
        inbound.setRemark(StringUtils.isNotBlank(inbound.getRemark())? inbound.getRemark() : "");
        inbound.setUpdateEmpId(loginInfo.getId());
        inbound.setUpdateEmp(loginInfo.getName());
        if (null == inbound.getId()) {
            inbound.setId(IdWorker.getId());
            inbound.setCustAccId(loginInfo.getCustAccId());
            String inStorePrefix = storeSetService.getInStorePrefix(loginInfo.getCustAccId());
            inbound.setCode(inStorePrefix + ZbOrderNoUtil.inStoreNo(loginInfo.getCustAccId()));
            inbound.setArchived(false);
            inbound.setReviewEmpId(0L);
            inbound.setReviewEmp("");
            inbound.setRejectEmpId(0L);
            inbound.setRejectEmp("");
            inbound.setRejectRemark("");
            inbound.setInboundEmpId(0L);
            inbound.setInboundEmp("");
            inbound.setInboundRemark("");
            inbound.setCancelEmpId(0L);
            inbound.setCancelEmp("");
            inbound.setCancelRemark("");
            inbound.setArchivedEmpId(0L);
            inbound.setArchivedEmp("");
            inbound.setArchivedRemark("");
            inbound.setAbatementInventory(false);
            inbound.setCreateEmpId(loginInfo.getId());
            inbound.setCreateEmp(loginInfo.getName());
        } else {
            inbound.setCode(inboundNo);
        }
        if (null != inboundVo.getCreateTime()) inbound.setGmtCreate(inboundVo.getCreateTime());
        // 保存并审核
        if (Objects.equals("2", submitType)) {
            inbound.setStatus(StoreConstant.STORE_IN_STATUS_2);
            inbound.setReviewEmpId(loginInfo.getId());
            inbound.setReviewEmp(loginInfo.getName());
            inbound.setReviewTime(new Date());
            inbound.setReviewRemark(StringUtils.isNotBlank(inboundVo.getReviewRemark())? inboundVo.getReviewRemark() : "");
        }
        // 工单配件入库，创建一物一码
        if (null != inboundOrderSpare) {
            getOrderSpareOutStoreCode(loginInfo, inbound.getCode(), boundMaterialVos, viewGoodsList, codeList);
        }
        storeInboundService.saveOrUpdate(inbound);

        List<ZjStoreInboundMaterial> addMaterialList = new ArrayList<>();
        List<ZjStoreInboundMaterial> updateMaterialList = new ArrayList<>();
        ZjStoreInboundMaterial material = null;
        List<ZjStoreInboundMaterialCode> materialCodeList = new ArrayList<>();
        ZjStoreInboundMaterialCode materialCode = null;
        List<ZjStoreGoodsStock> storeGoodsStockList = new ArrayList<>();
        ZjStoreGoodsStock storeGoodsStock = null;
        List<ZjStoreGoodsStockCode> storeGoodsStockCodeList = new ArrayList<>();
        // 仓库商品库存一物一码ID
        Long storeGoodsStockCodeId = null;
        ViewStoreStoreGoodsStock viewStoreStoreGoodsStock = null;

        for (StoreBoundMaterialVo vo : boundMaterialVos) {
            material = new ZjStoreInboundMaterial();
            BeanUtil.copyProperties(vo, material);
            material.setStatus(Integer.parseInt(submitType));
            if (null == material.getId()) {
                material.setId(IdWorker.getId());
                material.setCustAccId(loginInfo.getCustAccId());
                material.setStoreInboundId(inbound.getId());
                addMaterialList.add(material);
            } else {
                updateMaterialList.add(material);
            }
            // 仓库库存
            viewStoreStoreGoodsStock = storeStoreGoodsStockList.stream().filter(f -> Objects.equals(f.getId(), vo.getStoreId()) && Objects.equals(f.getStorePositionId(), vo.getStorePositionId()) &&
                    Objects.equals(f.getGoodsType(), vo.getType()) && Objects.equals(f.getGoodsId(), vo.getGoodsId()) && Objects.equals(f.getGoodsSpecId(), vo.getGoodsSpecId())).findFirst().orElse(null);
            // 仓库商品库存
            storeGoodsStock = new ZjStoreGoodsStock();
            storeGoodsStock.setId(null == viewStoreStoreGoodsStock? IdWorker.getId() : viewStoreStoreGoodsStock.getStoreGoodsStockId());
            storeGoodsStock.setCustAccId(loginInfo.getCustAccId());
            storeGoodsStock.setStoreId(vo.getStoreId());
            storeGoodsStock.setStorePositionId(vo.getStorePositionId());
            storeGoodsStock.setGoodsType(vo.getType());
            storeGoodsStock.setGoodsId(vo.getGoodsId());
            storeGoodsStock.setGoodsSpecId(vo.getGoodsSpecId());
            storeGoodsStock.setSystemStock(Objects.equals("1", submitType) ? 0L : new BigDecimal(vo.getQty() + "").longValue());
            storeGoodsStock.setPrice(vo.getPrice());
            storeGoodsStockList.add(storeGoodsStock);
            // 入库物料一物一码
            if (CollectionUtil.isNotEmpty(vo.getStockCodeVos())) {
                for (StoreGoodsStockCodeVo code : vo.getStockCodeVos()) {
                    Long codeId = codeList.stream().filter(f -> Objects.equals(f.getSecurityCode(), code.getCode()) && Objects.equals(f.getGoodsId(), vo.getGoodsId())
                            && Objects.equals(f.getType(), vo.getType()) && Objects.equals(f.getGoodsSpecId(), vo.getGoodsSpecId())).map(ZjCode::getId).findFirst().get();
                    // 非工单配件入库执行
                    if (null == inboundOrderSpare) {
                        // 设置一物一码更新信息
                        codeList.stream().filter(f -> Objects.equals(f.getId(), codeId)).forEach(t -> {
                            t.setStoreId(vo.getStoreId());
                            t.setStorePositionId(vo.getStorePositionId());
                            t.setStoreStatus(Objects.equals("2", submitType) ? CodeConstant.STORE_STATUS_3 : CodeConstant.STORE_STATUS_2);
                        });
                    }
                    if (null == existCodeMap.get(code.getCode())) {
                        materialCode = new ZjStoreInboundMaterialCode();
                        materialCode.setId(IdWorker.getId());
                        materialCode.setCustAccId(loginInfo.getCustAccId());
                        materialCode.setStoreInboundId(inbound.getId());
                        materialCode.setStoreInboundMaterialId(material.getId());
                        materialCode.setType(vo.getType());
                        materialCode.setCodeId(codeId);
                        materialCode.setCode(code.getCode());
                        materialCodeList.add(materialCode);
                    }
                    // 仓库商品库存一物一码
                    storeGoodsStockCodeId = storeGoodsStockCodes.stream().filter(f -> Objects.equals(f.getCode(), code.getCode())).findFirst().map(ZjStoreGoodsStockCode::getId).orElse(null);
                    storeGoodsStockCode = new ZjStoreGoodsStockCode();
                    storeGoodsStockCode.setInStoreType(Integer.parseInt(submitType));
                    storeGoodsStockCode.setStoreInboundId(inbound.getId());
                    storeGoodsStockCode.setStoreInboundCode(inbound.getCode());
                    storeGoodsStockCode.setStoreInboundMaterialId(material.getId());
                    storeGoodsStockCode.setOutStoreType(0);
                    storeGoodsStockCode.setStoreOutboundId(0L);
                    storeGoodsStockCode.setStoreOutboundCode("");
                    storeGoodsStockCode.setStoreOutboundMaterialId(0L);
                    if (null == storeGoodsStockCodeId) {
                        storeGoodsStockCode.setCustAccId(loginInfo.getCustAccId());
                        storeGoodsStockCode.setStoreId(vo.getStoreId());
                        storeGoodsStockCode.setStorePositionId(vo.getStorePositionId());
                        storeGoodsStockCode.setStoreGoodsStockId(storeGoodsStock.getId());
                        storeGoodsStockCode.setCodeId(codeId);
                        storeGoodsStockCode.setCode(code.getCode());
                    } else {
                        storeGoodsStockCode.setId(storeGoodsStockCodeId);
                    }
                    storeGoodsStockCodeList.add(storeGoodsStockCode);
                }
            }
        }
        // 根据删除的一物一码ID，获取商品库存一物一码信息
        List<Long> delStoreGoodsStockCodeIds = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(delCodeIds)) {
            List<ZjStoreGoodsStockCode> stockCodeList = storeGoodsStockCodeService.getByCodeIds(loginInfo.getCustAccId(), delCodeIds);
            delStoreGoodsStockCodeIds.addAll(stockCodeList.stream().map(ZjStoreGoodsStockCode::getId).toList());
        }
        // 删除入库物料 & 入库物料一物一码
        if (CollectionUtil.isNotEmpty(inboundVo.getDelInboundMaterialIds())){
            storeInboundMaterialService.removeByIds(inboundVo.getDelInboundMaterialIds());
        }
        storeInboundMaterialCodeService.deletebyCodeIds(delCodeIds);
        // 删除仓库商品库存一物一码
        storeGoodsStockCodeService.deleteByIds(delStoreGoodsStockCodeIds);

        // 入库物料
        if (CollectionUtil.isNotEmpty(addMaterialList)) storeInboundMaterialService.saveBatch(addMaterialList);
        if (CollectionUtil.isNotEmpty(updateMaterialList)) storeInboundMaterialService.updateBatchById(updateMaterialList);
        // 入库物料一物一码
        storeInboundMaterialCodeService.saveBatch(materialCodeList);
        // 仓库商品库存
        storeGoodsStockService.save(storeGoodsStockList, storeGoodsStockCodeList);

        if (null != inboundOrderSpare) {
            inboundOrderSpare.setStoreInboundId(inbound.getId());
            storeInboundOrderSpareService.save(inboundOrderSpare);
            StoreBoundServiceLog.saveInboundLog(new StoreBoundVo(loginInfo, inbound.getId(), inbound.getCode(), "工单配件入库", inboundVo.getRemark()));
        } else {
            // 更改一物一码前，移除同时存在的一物一码ID
            delCodeIds.removeIf(f -> codeList.stream().map(ZjCode::getId).anyMatch(f2 -> Objects.equals(f2, f)));
            codeService.updateInbound(loginInfo, false, 1, delCodeIds);
            codeService.saveInbound(loginInfo, submitType, inbound.getCode(), inbound.getInboundTime(), codeList);
            StoreBoundServiceLog.saveInboundLog(new StoreBoundVo(loginInfo, inbound.getId(), inbound.getCode(),
                    Objects.equals("2", submitType) ? "保存并审核入库单" : "新增入库单", inboundVo.getRemark()));
        }
    }

    /**
     * 校验仓库
     * @param codes
     * @param boundMaterialVos
     * @param viewGoodsMap
     */
    private void checkStore(List<String> codes, List<ViewStoreStoreGoodsStock> storeStoreGoodsStockList, List<StoreBoundMaterialVo> boundMaterialVos, Map<String, ViewGoods> viewGoodsMap) {
        ViewGoods viewGoods = null;
        List<ZjStorePosition> storePositionList = storePositionService.getStorePositionNameByIds(boundMaterialVos.stream().map(StoreBoundMaterialVo::getStorePositionId)
                .filter(f -> null != f && f > 0).distinct().toList());
        ZjStore store = null;
        ZjStorePosition storePosition = null;
        for (StoreBoundMaterialVo vo : boundMaterialVos) {
            viewGoods = viewGoodsMap.get(vo.getType() + "_" + vo.getGoodsId() + "_" + vo.getGoodsSpecId());
            store = storeStoreGoodsStockList.stream().filter(f -> Objects.equals(f.getId(), vo.getStoreId())).findFirst().orElse(null);
            Assert.notNull(store, "商品型号规格[ "+ viewGoods.getModel() + " " + viewGoods.getSpecName() +" ]的入库仓库参数[ "+vo.getStoreId()+" ]的数据不存在");

            if (store.getEnableStorePosition()) {
                // 校验仓位数据是否正确
                storePosition = storePositionList.stream().filter(f -> Objects.equals(f.getId(), vo.getStorePositionId())).findFirst().orElse(null);
                Assert.notNull(storePosition, "入库商品型号规格[ "+ viewGoods.getModel() + " " + viewGoods.getSpecName() +" ]的入库仓位[ "+vo.getStorePositionId()+" ]的数据不存在");
                // 校验仓库与仓位是否对应
                Assert.isTrue(Objects.equals(store.getId(), storePosition.getStoreId()),
                        "商品型号规格[ "+ viewGoods.getModel() + " " + viewGoods.getSpecName() +" ]入库仓位[ "+storePosition.getName()+" ]不属于仓库[ "+store.getName()+" ]下的仓位");
            }
            // 存储入库物料一物一码
            if (CollectionUtil.isNotEmpty(vo.getStockCodeVos())) codes.addAll(vo.getStockCodeVos().stream().map(StoreGoodsStockCodeVo::getCode).distinct().toList());
        }
    }

    /**
     * 校验一物一码
     * @param loginInfo
     * @param codeList
     * @param codes
     * @param storeType
     * @param typeId
     * @param inboundId
     * @param storeGoodsStockCodes
     * @param boundMaterialVos
     * @param viewGoodsList
     */
    private void checkCode(AccounLoginInfo loginInfo, List<ZjCode> codeList, List<String> codes, ZjStoreType storeType, Long typeId, Long inboundId, List<ZjStoreGoodsStockCode> storeGoodsStockCodes, List<StoreBoundMaterialVo> boundMaterialVos,
                           List<ViewGoods> viewGoodsList) {
        codeList.addAll(codeService.checkByCodes(loginInfo.getCustAccId(), codes));
        storeGoodsStockCodes.addAll(storeGoodsStockCodeService.getByCodes(loginInfo.getCustAccId(), codes));
        // 无效一物一码集合
        List<String> invalidCodes = new ArrayList<>();
        Map<String, Boolean> existCode = new HashMap<>();
        ViewGoods viewGoods = null;
        ZjStoreGoodsStockCode storeGoodsStockCode = null;
        for (StoreBoundMaterialVo vo : boundMaterialVos) {
            viewGoods = viewGoodsList.stream().filter(f -> Objects.equals(f.getGoodsType(), vo.getType()) && Objects.equals(f.getId(), vo.getGoodsId())
                    && Objects.equals(f.getSpecId(), vo.getGoodsSpecId())).findFirst().orElse(null);
            // 校验入库物料与一物一码数量
            Assert.isTrue(vo.getQty() == vo.getStockCodeVos().stream().map(StoreGoodsStockCodeVo::getCode).filter(StringUtils::isNotBlank).toList().size(), "商品型号规格[ " + viewGoods.getModel() + " " + viewGoods.getSpecName() + " ]数量与商品一物一码数量不一至");
            // 校验一物一码是否重复
            for (StoreGoodsStockCodeVo code : vo.getStockCodeVos()) {
                Assert.isNull(existCode.get(code.getCode()), "入库商品型号规格[ " + viewGoods.getModel() + " " + viewGoods.getSpecName() + " ]与商品一物一码[ " + code.getCode() + " ]已重复");
                existCode.put(code.getCode(), true);
            }
            // 校验一物一码是否在系统中
            invalidCodes.addAll(vo.getStockCodeVos().stream().map(StoreGoodsStockCodeVo::getCode).filter(f -> codeList.stream().noneMatch(f2 -> Objects.equals(f2.getSecurityCode(), f))).toList());
            Assert.isTrue(CollectionUtil.isEmpty(invalidCodes), "入库商品型号规格[ " + viewGoods.getModel() + " " + viewGoods.getSpecName() + " ]与绑定的一物一码[ " +
                    String.join("、", invalidCodes) + " ]在系统中不存在");
            // 校验物料与一物一码是否对应
            invalidCodes.clear();
            invalidCodes.addAll(vo.getStockCodeVos().stream().filter(f -> codeList.stream().noneMatch(f2 -> Objects.equals(f2.getType(), vo.getType()) && Objects.equals(f2.getSecurityCode(), f.getCode())
                    && Objects.equals(f2.getGoodsId(), vo.getGoodsId()) && Objects.equals(f2.getGoodsSpecId(), vo.getGoodsSpecId()))).map(StoreGoodsStockCodeVo::getCode).toList());
            Assert.isTrue(CollectionUtil.isEmpty(invalidCodes), "入库商品型号规格[ " + viewGoods.getModel() + " " + viewGoods.getSpecName() + " ]与绑定的一物一码[ " +
                    String.join("、", invalidCodes) + " ]不匹配，请检查型号规格与一物一码是否错误");

            // 非工单旧件入库时执行
            if (!Objects.equals(storeType.getId(), typeId) && !storeType.getInStoreOrderSpareType()) {
                // 校验一物一码是否已经出库
                invalidCodes.clear();
                invalidCodes.addAll(vo.getStockCodeVos().stream().map(StoreGoodsStockCodeVo::getCode).filter(f -> storeGoodsStockCodes.stream().anyMatch(f2 -> Objects.equals(f2.getCode(), f)
                        && (Objects.equals(f2.getOutStoreType(), StoreConstant.GOODS_CODE_OUT_STORE_TYPE_1) || Objects.equals(f2.getOutStoreType(), StoreConstant.GOODS_CODE_OUT_STORE_TYPE_2)))).toList());
                Assert.isTrue(CollectionUtil.isEmpty(invalidCodes), "入库商品型号规格[ " + viewGoods.getModel() + " " + viewGoods.getSpecName() + " ]与绑定的一物一码[ " +
                        String.join("、", invalidCodes) + " ]已经出库，禁止重复入库");

                // 校验一物一码是否已经入库
                invalidCodes.clear();
                if (null == inboundId) {
                    invalidCodes.addAll(vo.getStockCodeVos().stream().map(StoreGoodsStockCodeVo::getCode).filter(f -> storeGoodsStockCodes.stream().anyMatch(f2 -> Objects.equals(f2.getCode(), f)
                            && (Objects.equals(f2.getInStoreType(), StoreConstant.GOODS_CODE_IN_STORE_TYPE_1) || Objects.equals(f2.getInStoreType(), StoreConstant.GOODS_CODE_IN_STORE_TYPE_2)))).toList());
                    Assert.isTrue(CollectionUtil.isEmpty(invalidCodes), "入库商品型号规格[ " + viewGoods.getModel() + " " + viewGoods.getSpecName() + " ]与绑定的一物一码[ " +
                            String.join("、", invalidCodes) + " ]已经入库，禁止重复入库");
                } else {
                    for (StoreGoodsStockCodeVo codeVo : vo.getStockCodeVos()) {
                        storeGoodsStockCode = storeGoodsStockCodes.stream().filter(f -> Objects.equals(f.getCode(), codeVo.getCode())).findFirst().orElse(null);
                        if (null != storeGoodsStockCode && storeGoodsStockCode.getStoreInboundId() > 0 && !Objects.equals(storeGoodsStockCode.getStoreInboundId(), inboundId)) {
                            Assert.isTrue(false, "入库商品型号规格[ " + viewGoods.getModel() + " " + viewGoods.getSpecName() + " ]与绑定的一物一码[ " +
                                    codeVo.getCode() + " ]已经入库，禁止重复入库");
                        }
                    }
                }
            }
            vo.getStockCodeVos().forEach(t -> {
                t.setCodeId(codeList.stream().filter(f -> Objects.equals(f.getSecurityCode(), t.getCode())).map(ZjCode::getId).findFirst().orElse(0L));
            });
        }
    }

    // 工单配件出库，创建临时编码
    private void getOrderSpareOutStoreCode(AccounLoginInfo loginInfo, String inboundNo, List<StoreBoundMaterialVo> materialVos, List<ViewGoods> viewGoodsList, List<ZjCode> codeList) {
        // 工单配件出库，创建临时编码
//        List<CodeVo> codeVos = new ArrayList<>();
//        ViewGoods viewGoods = null;
//        for (StoreBoundMaterialVo vo : materialVos) {
//            viewGoods = viewGoodsList.stream().filter(f -> Objects.equals(f.getId(), vo.getGoodsId()) && Objects.equals(f.getSpecId(), vo.getGoodsSpecId())).findFirst().get();
//            CodeVo codeVo = new CodeVo();
//            codeVo.setGoodsId(vo.getGoodsId());
//            codeVo.setGoodsSpecId(vo.getGoodsSpecId());
//            codeVo.setQty((int) vo.getQty());
//            codeVo.setWarrantyDay(viewGoods.getWarrantyDay());
//            codeVo.setStoreId(vo.getStoreId());
//            codeVo.setStoreIdPositionId(vo.getStorePositionId());
//            codeVos.add(codeVo);
//        }
//        Map<String, List<ZjCode>> codeMap = conCodeService.saveSpareTemporaryCode(loginInfo, false, inboundNo, codeVos);
//        for (StoreBoundMaterialVo vo : materialVos) {
//            codeList.addAll(codeMap.get(vo.getGoodsId() + "_" + vo.getGoodsSpecId()));
//            vo.setStockCodeVos(codeList.stream().map(code -> {
//                return new StoreGoodsStockCodeVo(null, code.getSecurityCode());
//            }).toList());
//        }
    }

    // 获取入库列表
    @Override
    public Map<String, Object> getList(Long custAccId, StoreOutboundListSelectVo selectVo) {
        PageUtil.setPageLimit(selectVo);
        List<ZjStoreInbound> inboundList = storeInboundService.getList(custAccId, selectVo);
        List<ZjStoreType> storeTypes = storeTypeService.getNameByIds(inboundList.stream().map(ZjStoreInbound::getTypeId).distinct().toList());
        List<StoreInboundMaterialExtend> materialExtends = storeInboundMaterialService.getbyStoreInboundIds(inboundList.stream().map(ZjStoreInbound::getId).toList());
        List<StoreInboundListVo> voList = inboundList.stream().map(inbound -> {
            StoreInboundListVo vo = new StoreInboundListVo();
            BeanUtil.copyProperties(inbound, vo);
            vo.setInboundNo(inbound.getCode());
            storeTypes.stream().filter(f -> Objects.equals(f.getId(), inbound.getTypeId())).map(ZjStoreType::getName).findFirst().ifPresent(vo::setType);
            vo.setCreateTime(inbound.getGmtCreate());
            vo.setUpdateTime(inbound.getGmtUpdate());
            vo.setStore(materialExtends.stream().filter(f -> Objects.equals(f.getStoreInboundId(), inbound.getId())).distinct().map(extend -> {
                return extend.getStore()+ (StringUtils.isNotBlank(extend.getStorePosition())? " " + extend.getStorePosition() : "");
            }).toList());
            return vo;
        }).toList();
        return PageUtil.pageList(selectVo.getPage(), selectVo.getLimit(), storeInboundService.getListCount(custAccId, selectVo), voList);
    }

    // 根据入库单ID获取入库单详情
    @Override
    public StoreInboundDetailVo getInboundDetail(Long id) {
        ZjStoreInbound inbound = storeInboundService.getById(id);
        Assert.notNull(inbound, "入库单参数[ "+id+" ]的入库数据不存在");
        StoreInboundDetailVo vo = new StoreInboundDetailVo();
        BeanUtil.copyProperties(inbound, vo);
        vo.setInboundNo(inbound.getCode());
        vo.setCreateTime(inbound.getGmtCreate());
        vo.setUpdateTime(inbound.getGmtUpdate());
        vo.setType(storeTypeService.getById(inbound.getTypeId()).getName());
        ZjStoreLogistics logistics = storeLogisticsService.getById(id);
        if (null != logistics) {
            vo.setLogisticsName(logistics.getCompany());
            vo.setLogisticsNo(logistics.getLogisticsNo());
            vo.setLogisticsRemark(logistics.getRemark());
        }
        return vo;
    }

    // 根据入库单ID获取入库单详情物料
    @Override
    public List<OutInboundMaterialVo> getInboundDetailMaterial(Long id) {
        List<StoreInboundMaterialExtend> materialExtends = storeInboundMaterialService.getMaterialsStockbyStoreInboundId(id);
        List<ViewGoods> viewGoodsList = viewGoodsService.getByGoodsIdsAndGoodsSpecIds(materialExtends.stream().map(StoreInboundMaterialExtend::getGoodsId).distinct().toList(),
                materialExtends.stream().map(StoreInboundMaterialExtend::getGoodsSpecId).distinct().toList());
        List<ZjStoreInboundMaterialCode> materialCodes = storeInboundMaterialCodeService.getbyStoreInboundId(id);
        return materialExtends.stream().map(material -> {
            OutInboundMaterialVo vo = new OutInboundMaterialVo();
            BeanUtil.copyProperties(material, vo);
            viewGoodsList.stream().filter(f -> Objects.equals(f.getGoodsType(), material.getType()) && Objects.equals(f.getId(), material.getGoodsId())
                    && Objects.equals(f.getSpecId(), material.getGoodsSpecId())).findFirst().ifPresent(goods -> {
                vo.setGoodsBrand(goods.getBrand());
                vo.setGoodsName(goods.getName());
                vo.setGoodsModel(goods.getModel());
                vo.setGoodsType(goods.getType());
                vo.setGoodsUnit(goods.getUnit());
                vo.setGoodsSpecName(goods.getSpecName());
            });
            vo.setStockCodeVos(materialCodes.stream().filter(f -> Objects.equals(f.getStoreInboundMaterialId(), material.getId())).map(code -> {
                return new StoreGoodsStockCodeVo(code.getCodeId(), code.getCode());
            }).toList());
            return vo;
        }).toList();
    }

    // 确认入库
    @Override
    @Transactional
    public void saveSureInbound(AccounLoginInfo loginInfo, Long id, StoreInboundLogisticsVo logisticsVo) {
        ZjStoreInbound inbound = storeInboundService.getById(id);
        Assert.notNull(inbound, "入库单参数[ " + id + " ]的数据不存在");
        Assert.isTrue(Objects.equals(StoreConstant.STORE_IN_STATUS_2, inbound.getStatus()),
                Objects.equals(StoreConstant.STORE_IN_STATUS_1, inbound.getStatus()) ? "入库单未审核，禁止操作入库" :
                        Objects.equals(StoreConstant.STORE_IN_STATUS_3, inbound.getStatus()) ? "入库单已被审核并驳回，禁止入库" :
                                Objects.equals(StoreConstant.STORE_IN_STATUS_4, inbound.getStatus()) ? "入库单已审核完成并入库，禁止重复入库" : "入库单已作废，禁止重复操作"
        );
        ZjStoreInbound updateInbound = new ZjStoreInbound();
        updateInbound.setId(id);
        updateInbound.setStatus(StoreConstant.STORE_IN_STATUS_4);
        updateInbound.setInboundEmpId(loginInfo.getId());
        updateInbound.setInboundEmp(loginInfo.getName());
        updateInbound.setInboundRemark(logisticsVo.getRemark());
        updateInbound.setInboundTime(new Date());
        updateInbound.setUpdateEmpId(loginInfo.getId());
        updateInbound.setUpdateEmp(loginInfo.getName());

        List<ZjStoreInboundMaterialCode> inboundMaterialCodeList = storeInboundMaterialCodeService.getbyStoreInboundId(id);
        boolean sureCodeAndInStore = CollectionUtil.isEmpty(inboundMaterialCodeList);
        if (sureCodeAndInStore) {
            List<StoreBoundMaterialVo> materialVos = logisticsVo.getInBoundMaterialVos();
            Assert.notEmpty(materialVos, "该入库物料没有指定一物一码，请必须绑定一物一码才可入库");
            // 获取存在的物料
            List<ZjStoreInboundMaterial> inboundMaterialList = storeInboundMaterialService.getbyStoreInboundId(id);
            ZjStoreInboundMaterial inboundMaterial = null;

            // 校验入库物料与原入库物料是否一致
            for (StoreBoundMaterialVo vo : materialVos) {
                Assert.notNull(vo.getId(), "确认入库时，入库物料ID参数不能为空");
                vo.setStorePositionId(null == vo.getStorePositionId()? 0 : vo.getStorePositionId());
                inboundMaterial = inboundMaterialList.stream().filter(f -> Objects.equals(f.getType(), vo.getType())
                        && Objects.equals(f.getGoodsId(), vo.getGoodsId()) && Objects.equals(f.getGoodsSpecId(), vo.getGoodsSpecId())).findFirst().orElse(null);
                Assert.isTrue(Objects.equals(inboundMaterial.getId(), vo.getId()), "确认入库时，入库物料ID参数与原入库物料参数ID不一致");
                // 校验物料
                Assert.notNull(inboundMaterial, "入库的物料与原入库的物料不一致");
            }
            List<Long> goodsIds = inboundMaterialList.stream().map(ZjStoreInboundMaterial::getGoodsId).distinct().toList();
            List<Long> goodsSpecIds = inboundMaterialList.stream().map(ZjStoreInboundMaterial::getGoodsSpecId).distinct().toList();
            List<ViewGoods> viewGoodsList = viewGoodsService.getByGoodsIdsAndGoodsSpecIds(goodsIds, goodsSpecIds);

            Map<String, ViewGoods> viewGoodsMap = new HashMap<>();
            // 校验入库仓库原物料入库仓库是否一致
            ViewGoods viewGoods = null;
            for (StoreBoundMaterialVo vo : materialVos) {
                viewGoods = viewGoodsList.stream().filter(f -> Objects.equals(f.getGoodsType(), vo.getType()) && Objects.equals(f.getId(), vo.getGoodsId()) &&
                        Objects.equals(f.getSpecId(), vo.getGoodsSpecId())).findFirst().orElse(null);
                if (null == viewGoods) {
                    continue;
                }
                viewGoodsMap.putIfAbsent(vo.getType() + "_" + vo.getGoodsId() + "_" + vo.getGoodsSpecId(), viewGoods);

                inboundMaterial = inboundMaterialList.stream().filter(f -> Objects.equals(f.getId(), vo.getId()) && Objects.equals(f.getType(), vo.getType()) &&
                        Objects.equals(f.getGoodsId(), vo.getGoodsId()) && Objects.equals(f.getGoodsSpecId(), vo.getGoodsSpecId())).findFirst().get();
                // 判断仓库
                Assert.isTrue(Objects.equals(vo.getStoreId(), inboundMaterial.getStoreId()),
                        "物料型号规格[ "+viewGoods.getModel()+ "、"+ viewGoods.getSpecName() +" ]的出库仓库与原出库仓库不一致");
                // 判断仓位
                Assert.isTrue(Objects.equals(vo.getStorePositionId(), inboundMaterial.getStorePositionId()),
                        "物料型号规格[ "+viewGoods.getModel()+ "、"+ viewGoods.getSpecName() +" ]的出库仓位与原出库仓位不一致");
            }
            // 获取仓库ID获取仓库及仓库商品库存
            List<Long> storeIds = materialVos.stream().map(StoreBoundMaterialVo::getStoreId).distinct().toList();
            List<ViewStoreStoreGoodsStock> storeStoreGoodsStockList = viewStoreStoreGoodsStockService.getByStoreIds(storeIds);
            // 校验仓库
            List<String> codes = new ArrayList<>();
            checkStore(codes, storeStoreGoodsStockList, materialVos, viewGoodsMap);

            ZjStoreType storeType = storeTypeService.getById(inbound.getTypeId());
            List<ZjStoreGoodsStockCode> storeGoodsStockCodes = new ArrayList<>();
            List<ZjCode> codeList = new ArrayList<>();
            // 校验一物一码
            checkCode(loginInfo, codeList, codes, storeType, inbound.getTypeId(), inbound.getId(), storeGoodsStockCodes, materialVos, viewGoodsList);

            ZjStoreInboundMaterialCode materialCode = null;
            List<ZjStoreGoodsStockCode> storeGoodsStockCodeList = new ArrayList<>();
            ZjStoreGoodsStockCode storeGoodsStockCode = null;
            Long storeGoodsStockCodeId = null;
            for (StoreBoundMaterialVo vo : materialVos) {
                for (StoreGoodsStockCodeVo code : vo.getStockCodeVos()) {
                    materialCode = new ZjStoreInboundMaterialCode();
                    materialCode.setId(IdWorker.getId());
                    materialCode.setCustAccId(loginInfo.getCustAccId());
                    materialCode.setStoreInboundId(id);
                    materialCode.setStoreInboundMaterialId(vo.getId());
                    materialCode.setType(vo.getType());
                    materialCode.setCodeId(code.getCodeId());
                    materialCode.setCode(code.getCode());
                    inboundMaterialCodeList.add(materialCode);

                    // 设置一物一码更新信息
                    codeList.stream().filter(f -> Objects.equals(f.getId(), code.getCodeId())).forEach(t -> {
                        t.setStoreId(vo.getStoreId());
                        t.setStorePositionId(vo.getStorePositionId());
                        t.setStoreStatus(CodeConstant.STORE_STATUS_3);
                    });
                    // 仓库商品库存一物一码
                    storeGoodsStockCodeId = storeGoodsStockCodes.stream().filter(f -> Objects.equals(f.getCode(), code.getCode())).findFirst().map(ZjStoreGoodsStockCode::getId).orElse(null);
                    storeGoodsStockCode = new ZjStoreGoodsStockCode();
                    storeGoodsStockCode.setInStoreType(2);
                    storeGoodsStockCode.setStoreInboundId(inbound.getId());
                    storeGoodsStockCode.setStoreInboundCode(inbound.getCode());
                    storeGoodsStockCode.setStoreInboundMaterialId(vo.getId());
                    storeGoodsStockCode.setOutStoreType(0);
                    storeGoodsStockCode.setStoreOutboundId(0L);
                    storeGoodsStockCode.setStoreOutboundCode("");
                    storeGoodsStockCode.setStoreOutboundMaterialId(0L);
                    if (null == storeGoodsStockCodeId) {
                        // 仓库商品库存
                        storeGoodsStockCode.setCustAccId(loginInfo.getCustAccId());
                        storeGoodsStockCode.setStoreId(vo.getStoreId());
                        storeGoodsStockCode.setStorePositionId(vo.getStorePositionId());
                        storeGoodsStockCode.setStoreGoodsStockId(storeStoreGoodsStockList.stream().filter(f -> Objects.equals(f.getId(), vo.getStoreId()) &&
                                        Objects.equals(f.getStorePositionId(), vo.getStorePositionId()) && Objects.equals(f.getGoodsType(), vo.getType()) &&
                                        Objects.equals(f.getGoodsId(), vo.getGoodsId()) && Objects.equals(f.getGoodsSpecId(), vo.getGoodsSpecId()))
                                .findFirst().map(ViewStoreStoreGoodsStock::getStoreGoodsStockId).orElse(0L));
                        storeGoodsStockCode.setCodeId(code.getCodeId());
                        storeGoodsStockCode.setCode(code.getCode());
                    } else {
                        storeGoodsStockCode.setId(storeGoodsStockCodeId);
                    }
                    storeGoodsStockCodeList.add(storeGoodsStockCode);
                }
            }
            storeInboundMaterialCodeService.saveBatch(inboundMaterialCodeList);
            storeGoodsStockCodeService.saveOrUpdateBatchById(storeGoodsStockCodeList);
            codeService.saveInbound(loginInfo, "3", inbound.getCode(), updateInbound.getInboundTime(), codeList);
        }

        // 避免重复更新编码
        if (!sureCodeAndInStore) {
            List<Long> codeIds = inboundMaterialCodeList.stream().map(ZjStoreInboundMaterialCode::getCodeId).toList();
            codeService.updateCodeByOutInbound(loginInfo, codeIds, updateInbound.getInboundTime(), false);
        }
        storeInboundService.updateById(updateInbound);
        storeLogisticsService.saveInboundLogistics(loginInfo.getCustAccId(), id,
                new StoreLogisticsVo().setStoreOutboundCode(inbound.getCode())
                        .setLogisticsName(logisticsVo.getLogisticsName())
                        .setLogisticsCode(logisticsVo.getLogisticsCode())
                        .setLogisticsNo(logisticsVo.getLogisticsNo())
                        .setRemark(logisticsVo.getRemark())
                        .setTime(updateInbound.getInboundTime()));
        StoreBoundServiceLog.saveInboundLog(new StoreBoundVo(loginInfo, inbound.getId(), inbound.getCode(),"确认收货并入库", logisticsVo.getRemark()));
    }

    // 作废入库单
    @Override
    @Transactional
    public void cancelStoreInbound(AccounLoginInfo loginInfo, Long id, String remark) {
        ZjStoreInbound inbound = storeInboundService.getById(id);
        Assert.notNull(inbound, "入库单参数[ " + id + " ]的数据不存在");
        Assert.isTrue(Objects.equals(StoreConstant.STORE_IN_STATUS_1, inbound.getStatus()) || Objects.equals(StoreConstant.STORE_IN_STATUS_2, inbound.getStatus()),
                Objects.equals(StoreConstant.STORE_IN_STATUS_3, inbound.getStatus()) ? "入库单已被审核并驳回，禁止重复作废" :
                        Objects.equals(StoreConstant.STORE_IN_STATUS_4, inbound.getStatus()) ? "入库单已审核完成并入库，禁止作废" : "入库单已作废，禁止重复操作"
        );
        ZjStoreInbound updateInbound = new ZjStoreInbound();
        updateInbound.setId(id);
        updateInbound.setStatus(StoreConstant.STORE_IN_STATUS_5);
        updateInbound.setCancelEmpId(loginInfo.getId());
        updateInbound.setCancelEmp(loginInfo.getName());
        updateInbound.setCancelRemark(remark);
        updateInbound.setCancelTime(new Date());
        updateInbound.setUpdateEmpId(loginInfo.getId());
        updateInbound.setUpdateEmp(loginInfo.getName());
        exceuteUpdate(loginInfo, inbound, true);
        storeInboundService.updateById(updateInbound);
    }

    // 驳回入库单
    @Override
    public void rejectInbound(AccounLoginInfo loginInfo, Long id, String remark) {
        ZjStoreInbound inbound = storeInboundService.getById(id);
        Assert.notNull(inbound, "入库单参数[ " + id + " ]的数据不存在");
        Assert.isTrue(Objects.equals(StoreConstant.STORE_IN_STATUS_1, inbound.getStatus()),
                Objects.equals(StoreConstant.STORE_IN_STATUS_2, inbound.getStatus()) ? "入库单已审核，禁止驳回的反向操作" :
                        Objects.equals(StoreConstant.STORE_IN_STATUS_3, inbound.getStatus()) ? "入库单已被审核并驳回，禁止重复驳回操作" :
                                Objects.equals(StoreConstant.STORE_IN_STATUS_4, inbound.getStatus()) ? "入库单已审核完成并入库，禁止重复入库" : "入库单已作废，禁止重复操作"
        );
        ZjStoreInbound updateInbound = new ZjStoreInbound();
        updateInbound.setId(id);
        updateInbound.setStatus(StoreConstant.STORE_IN_STATUS_3);
        updateInbound.setRejectEmpId(loginInfo.getId());
        updateInbound.setRejectEmp(loginInfo.getName());
        updateInbound.setRejectRemark(remark);
        updateInbound.setRejectTime(new Date());
        updateInbound.setUpdateEmpId(loginInfo.getId());
        updateInbound.setUpdateEmp(loginInfo.getName());
        exceuteUpdate(loginInfo, inbound, false);
        storeInboundService.updateById(updateInbound);
    }

    /**
     * 取消或驳回入库单执行更新的操作
     * @param loginInfo 登录信息
     * @param inbound 入库单对象
     * @param cancelInbound 是否取消入库单：true-是，false-不是，为驳回操作
     */
    private void exceuteUpdate(AccounLoginInfo loginInfo, ZjStoreInbound inbound, boolean cancelInbound) {
        // 更新商品库存
        List<ZjStoreInboundMaterial> inboundMaterialList = storeInboundMaterialService.getbyStoreInboundId(inbound.getId());
        List<ZjStoreGoodsStockCode> goodsStockCodeList = storeGoodsStockCodeService.getByStoreInboundId(inbound.getId());
        List<ZjStoreGoodsStock> updateStoreGoodsStockList = new ArrayList<>();
        // 入库单已审核
        if (Objects.equals(inbound.getStatus(), StoreConstant.STORE_OUT_STATUS_2)) {
            List<ZjStoreGoodsStock> storeGoodsStocks = new ArrayList<>();
            if (CollectionUtil.isNotEmpty(goodsStockCodeList)) {
                storeGoodsStocks.addAll(storeGoodsStockService.listByIds(goodsStockCodeList.stream().map(ZjStoreGoodsStockCode::getStoreGoodsStockId).distinct().toList()));
            }
            ZjStoreGoodsStock updateStoreGoodsStock = null;
            long inboundGoodsQty = 0;
            for (ZjStoreGoodsStock storeGoodsStock : storeGoodsStocks) {
                updateStoreGoodsStock = new ZjStoreGoodsStock();
                updateStoreGoodsStock.setId(storeGoodsStock.getId());
                inboundGoodsQty = inboundMaterialList.stream().filter(f -> goodsStockCodeList.stream().anyMatch(f2 -> Objects.equals(f2.getStoreGoodsStockId(), storeGoodsStock.getId()) && Objects.equals(f2.getStoreInboundMaterialId(), f.getId())))
                        .map(ZjStoreInboundMaterial::getQty).findFirst().orElse(0L);
                updateStoreGoodsStock.setSystemStock(new BigDecimal(storeGoodsStock.getSystemStock().toString()).subtract(new BigDecimal(inboundGoodsQty + "")).longValue());
                updateStoreGoodsStockList.add(updateStoreGoodsStock);
            }
        }
        List<Long> delStoreGoodsStockCodeIds = new ArrayList<>();
        List<ZjCode> updateCodeList = new ArrayList<>();
        ZjCode updateCode = null;
        for (ZjStoreGoodsStockCode stockCode : goodsStockCodeList) {
            delStoreGoodsStockCodeIds.add(stockCode.getId());
            updateCode = new ZjCode();
            updateCode.setId(stockCode.getCodeId());
            updateCode.setStoreStatus(CodeConstant.STORE_STATUS_1);
            updateCode.setStoreId(0L);
            updateCode.setStorePositionId(0L);
            updateCodeList.add(updateCode);
        }
        storeInboundMaterialService.updateStatusById(inbound.getId(), 3);
        if (CollectionUtil.isNotEmpty(updateStoreGoodsStockList)) storeGoodsStockService.updateBatchById(updateStoreGoodsStockList);
        if (CollectionUtil.isNotEmpty(delStoreGoodsStockCodeIds)) storeGoodsStockCodeService.deleteByIds(delStoreGoodsStockCodeIds);
        codeService.updateOutStoreActiveCode(loginInfo, false, cancelInbound, updateCodeList);
    }
}
